package postgres

import (
	"context"
	"gorm.io/gorm"
	"manager/errors"
	"manager/model"
	"manager/model/entity"
	"time"
)

var FirmwaresTactic = &firmwaresTactic{}

type firmwaresTactic struct{}

// Create 创建
func (a *firmwaresTactic) Create(ctx context.Context, m *entity.FirmwaresTactic) (int64, error) {
	err := GetDB(ctx).Create(m).Error
	return m.Id, err
}

// CheckExistFirmwareTactic 是否关联关键
func (a *firmwaresTactic) CheckExistFirmwareTactic(firmwareId int64) (int64, error) {
	var (
		q     = db.Debug().Model(&entity.FirmwaresTactic{})
		count int64
		err   error
	)
	err = q.Where("firmware_id =?", firmwareId).Count(&count).Limit(1).Error
	return count, err
}

func (a *firmwaresTactic) CheckExistActivePlanByRange(execRange int) (int64, error) {
	var (
		q     = db.Debug().Model(&entity.FirmwaresTactic{})
		count int64
		err   error
	)
	if execRange >= 0 {
		q.Where("exec_range =? ", execRange)
	}
	q.Where(" status!=?", 2)
	err = q.Count(&count).Error
	return count, err
}

// Find 查找详情
func (a *firmwaresTactic) Find(ctx context.Context, in *model.FirmwaresTacticInfoRequest) (*entity.FirmwaresTactic, error) {
	e := &entity.FirmwaresTactic{}

	q := GetDB(ctx).Model(&entity.FirmwaresTactic{})

	if in.Id > 0 {
		err := q.First(&e, in.Id).Error
		return e, err
	}

	count := 0

	if in.FirmwareId != nil {

		q = q.Where("firmware_id = ?", in.FirmwareId)

		count++
	}

	if in.ReleaseTime != nil {

		q = q.Where("release_time = ?", in.ReleaseTime)

		count++
	}

	if in.ReleaseType != nil {

		q = q.Where("release_type = ?", in.ReleaseType)

		count++
	}

	if in.UpgradeType != nil {

		q = q.Where("upgrade_type = ?", in.UpgradeType)

		count++
	}

	if in.ExecRange != nil {

		q = q.Where("exec_range = ?", in.ExecRange)

		count++
	}

	if in.Status != nil {

		q = q.Where("status = ?", in.Status)

		count++
	}

	if in.Desc != nil {

		q = q.Where("desc like ?", in.Desc)

		count++
	}

	if in.UpdatedAt != nil {

		q = q.Where("updated_at = ?", in.UpdatedAt)

		count++
	}

	if count == 0 {
		return e, errors.New("condition illegal")
	}

	err := q.First(&e).Error
	return e, err
}

// Update 更新
func (a *firmwaresTactic) Update(ctx context.Context, id int64, dict map[string]interface{}) error {
	return GetDB(ctx).Model(&entity.FirmwaresTactic{}).Where("id = ?", id).Updates(dict).Error
}

// Delete 删除
func (a *firmwaresTactic) Delete(ctx context.Context, id int64) error {
	return GetDB(ctx).Delete(&entity.FirmwaresTactic{}, id).Error
}

// List 列表查询
func (a *firmwaresTactic) List(ctx context.Context, in *model.FirmwaresTacticListRequest) (int, []*entity.FirmwaresTactic, error) {
	var (
		q                = GetDB(ctx).Model(&entity.FirmwaresTactic{})
		err              error
		total            int64
		firmwaresTactics []*entity.FirmwaresTactic
	)

	if in.FirmwareId != nil {

		q = q.Where("firmware_id = ?", in.FirmwareId)

	}

	if in.ReleaseTime != nil {

		q = q.Where("release_time = ?", in.ReleaseTime)

	}

	if in.ReleaseType != nil {

		q = q.Where("release_type = ?", in.ReleaseType)

	}

	if in.UpgradeType != nil {

		q = q.Where("upgrade_type = ?", in.UpgradeType)

	}

	if in.ExecRange != nil {

		q = q.Where("exec_range = ?", in.ExecRange)

	}

	if in.Status != nil {

		q = q.Where("status = ?", in.Status)

	}

	if in.Desc != nil {

		q = q.Where("desc like ?", in.Desc)

	}

	if in.UpdatedAt != nil {

		q = q.Where("updated_at = ?", in.UpdatedAt)

	}

	if len(in.TimeZone) == 2 {
		q = q.Where("created_at between ? and ?", in.TimeZone[0], in.TimeZone[1])
	}

	if err = q.Count(&total).Error; err != nil {
		return 0, nil, err
	}
	if err = q.Order("created_at desc").Limit(in.Size).Offset((in.Index - 1) * in.Size).Find(&firmwaresTactics).Error; err != nil {
		return 0, nil, err
	}
	return int(total), firmwaresTactics, nil
}

func (a *firmwaresTactic) FindUpgradePlanBySn(snCode string, status []int) (*model.UpgradePlanBySnResponse, error) {
	var (
		err         error
		upgradePlan = make([]*model.UpgradePlanBySnResponse, 0)
	)
	sqlStr := "SELECT FT.FIRMWARE_ID,UR.TACTICS_ID,F.VERSION,F.NAME as FIRMWARES_NAME ,FT.release_type,F.path " +
		"FROM UPGRADE_RECORDS UR " +
		"JOIN FIRMWARES_TACTICS FT ON UR.TACTICS_ID = FT.ID " +
		"JOIN FIRMWARES F ON FT.FIRMWARE_ID = F.ID " +
		"WHERE SN_CODE = ? " +
		"AND FT.STATUS = 3  " +
		"AND FT.RELEASE_TIME <= ? " +
		"AND  NOT EXISTS (SELECT DUR.FIRMWARE_ID FROM DEVICE_UPGRADE_RECODES DUR WHERE DUR.STATUS in ? AND DUR.SN_CODE=UR.SN_CODE AND DUR.VERSION = f.VERSION AND DUR.FIRMWARE_ID=UR.FIRMWARE_ID) " +
		"ORDER BY FT.FIRMWARE_ID DESC "
	err = db.Raw(sqlStr, snCode, time.Now().Unix(), status).Find(&upgradePlan).Error
	if len(upgradePlan) <= 0 {
		return nil, err
	}
	return upgradePlan[0], err
}

func (a *firmwaresTactic) FindUpgradePlanBySnAndType(snCode string, typeId int64) (*model.UpgradePlanBySnResponse, error) {
	var (
		err         error
		upgradePlan = make([]*model.UpgradePlanBySnResponse, 0)
	)
	sqlStr := "SELECT FT.FIRMWARE_ID,fr.TACTICS_ID,F.VERSION,F.NAME as FIRMWARES_NAME ,FT.release_type,F.path " +
		"FROM firmwares_records fr " +
		"JOIN FIRMWARES_TACTICS FT ON fr.TACTICS_ID = FT.ID " +
		"JOIN FIRMWARES F ON FT.FIRMWARE_ID = F.ID " +
		"WHERE ?=any(fr.ebikes_type) " +
		"AND FT.STATUS = 3 " +
		"AND FT.RELEASE_TIME <= ? " +
		"AND  NOT EXISTS (SELECT DUR.FIRMWARE_ID FROM DEVICE_UPGRADE_RECODES DUR WHERE DUR.SN_CODE=? AND DUR.VERSION = f.VERSION AND DUR.FIRMWARE_ID=fr.FIRMWARE_ID) " +
		"ORDER BY FT.FIRMWARE_ID DESC "
	err = db.Raw(sqlStr, typeId, time.Now().Unix(), snCode).Find(&upgradePlan).Error
	if len(upgradePlan) <= 0 {
		return nil, err
	}
	return upgradePlan[0], err
}

func (a *firmwaresTactic) FindUpgradePlanByAllAndSn(snCode string) (*model.UpgradePlanBySnResponse, error) {
	var (
		err         error
		upgradePlan = make([]*model.UpgradePlanBySnResponse, 0)
	)
	sqlStr := "SELECT FT.FIRMWARE_ID,FT.ID AS TACTICS_ID,F.VERSION,F.NAME AS FIRMWARES_NAME ,FT.release_type,F.path " +
		"FROM FIRMWARES_TACTICS FT " +
		"JOIN FIRMWARES F ON FT.FIRMWARE_ID = F.ID " +
		"WHERE FT.EXEC_RANGE = 0 " +
		"AND FT.STATUS = 3 " +
		"AND FT.RELEASE_TIME <= ? " +
		"AND  NOT EXISTS (SELECT DUR.FIRMWARE_ID FROM DEVICE_UPGRADE_RECODES DUR WHERE DUR.SN_CODE = ? AND DUR.VERSION = F.VERSION AND DUR.FIRMWARE_ID = FT.FIRMWARE_ID) " +
		"ORDER BY FT.FIRMWARE_ID DESC "
	err = db.Raw(sqlStr, time.Now().Unix(), snCode).Find(&upgradePlan).Error
	if len(upgradePlan) <= 0 {
		return nil, err
	}
	return upgradePlan[0], err
}

// ExecTransaction db事务执行
func (a *firmwaresTactic) ExecTransaction(ctx context.Context, callback func(ctx context.Context) error) error {
	return GetDB(ctx).Transaction(func(tx *gorm.DB) error {
		ctx = context.WithValue(ctx, DBCONTEXTKEY, tx)
		return callback(ctx)
	})
}
